/*
 *  $Id: HtmlStatisticCardExporter.cs 1215 2010-11-24 14:50:50Z thenn.erannor $
 *	This file is a part of Ragima CCG.
 *	(C) 2008-2010 Ragima development group.
 *
 *	Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Ragima {
    public class HtmlStatisticCardExporter : ICardExporter {
        public void Export(Stream stream, IEnumerable<Card> cards) {
            using (var writer = new StreamWriter(stream, Encoding.UTF8))
                Export(writer, cards);
        }

        private readonly static string[] RowNames = {
            "Всего карт",
            "По типам карт:", "Существа", "Местности", "Заклинания", "Чары", "Способности", "Способности игрока",
            "Пригодные для составления колод:", "Карты для колод", "Размер полной колоды", "Суммарный вес полной колоды", "Суммарный вес полной колоды (без отриц.)",
            "Отсутствие данных:", "Карты без названий", "Карты без описаний", "Карты без условий (бесплатные)",
            "Завершенность карт:", "Неизвестно", "TODO", "В процессе", "Готово", "Протестировано"
        };
        private readonly static int Rows = RowNames.Length;
        private const int rAll = 0;
        private const int rType = 2;
        private const int rDeck = 9;
        private const int rMiss = 14;
        private const int rLevel = 18;

        private const string StatsTitle = "Статистика по картам для игры Ragima";

        private void Export(TextWriter writer, IEnumerable<Card> cards) {
            int Cols = ElementType.Count + 1;
            int cAll = Cols - 1;
            var stats = new int[Rows, Cols];
            var statsAdd = new string[ElementType.Count, 5, 6];
            var statsMana = new int[21, 7, Cols];
            foreach (var card in cards) {
                if (card.CardType == CardType.Unknown) continue;
                int e = card.Element.Number;
                stats[rAll,cAll]++;
                stats[rAll,e]++;
                int type = (int) card.CardType - 1;
                stats[rType+type,cAll]++;
                stats[rType+type,e]++;
                if (type != 4) {
                    stats[rDeck,cAll]++;
                    stats[rDeck,e]++;
                    stats[rDeck+1,cAll] += card.MaxCount;
                    stats[rDeck+1,e] += card.MaxCount;
                    int weight = card.Weight * card.MaxCount;
                    stats[rDeck+2,cAll] += weight;
                    stats[rDeck+2,e] += weight;
                    if (weight > 0) {
                        stats[rDeck+3,cAll] += weight;
                        stats[rDeck+3,e] += weight;
                    }
                }
                bool hasName = !string.IsNullOrEmpty(card.Name.ToString()) && card.Name.HasResource(Application.Config.CurrentLanguage);
                if (!hasName) {
                    stats[rMiss,cAll]++;
                    stats[rMiss,e]++;
                }
                if (!card.HasDescription || string.Compare(card.Name.ToString(), card.DescriptionText, true) == 0) {
                    stats[rMiss+1,cAll]++;
                    stats[rMiss+1,e]++;
                }
                if (!card.HasConditions) {
                    stats[rMiss+2,cAll]++;
                    stats[rMiss+2,e]++;
                }
                int level = rLevel + (int) card.Level;
                stats[level,cAll]++;
                stats[level,e]++;

                int mana = card.GetSumMana();
                if (!card.IsAbility) {
                    statsMana[mana,6,cAll]++;
                    statsMana[mana,6,e]++;
                }
                statsMana[mana,type,cAll]++;
                statsMana[mana,type,e]++;

                level = (int) card.Level;
                string s = statsAdd[e, level, type];
                s = (string.IsNullOrEmpty(s) ? "" : s + ", ") + (!hasName ? card.GetType().Name : card.Name.ToString());
                statsAdd[e, level, type] = s;
            }

            var cardsByWeight = new List<Card>(cards);
            cardsByWeight.Sort((a, b) => {
                int r = a.Weight.CompareTo(b.Weight);
                if (r == 0) r = a.Id.CompareTo(b.Id);
                return r;
            });

            writer.WriteLine("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\n<title>{0}</title>\n</head>\n<body><h1>{0}</h1>", StatsTitle);

            writer.WriteLine("<table width=\"100%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">");
            writer.Write("<tr><th>&nbsp;</th>");
            foreach (var element in ElementType.AllElements)
                writer.Write("<th>{0}</th>", element.Name);
            writer.WriteLine("<th>ВСЕГО</th></tr>");
            for (int row = 0; row < Rows; row++) {
                if (RowNames[row].EndsWith(":")) {
                    writer.WriteLine("<tr><td colspan=\"{1}\" align=\"center\">{0}</td></tr>", RowNames[row], Cols+1);
                    continue;
                }
                writer.Write("<tr valign=\"top\"><td>{0}</td>", RowNames[row]);
                for (int col = 0; col < Cols; col++)
                    writer.Write("<td>{0}</td>", stats[row,col]);
                writer.WriteLine("</tr>");
            }
            writer.WriteLine("</table>");

            writer.WriteLine("<br/><br/>");

            writer.WriteLine("<h2>Статистика карт по ценам в мане.</h2><p>Каждая стихия разложена по столбцам: C - существа, L - местности, S - заклинания, E - чары, A - способности, P - способности игрока.</p>");
            writer.WriteLine("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"0\">");
            writer.Write("<tr><th rowspan=\"2\">Цена в мане</th>");
            foreach (var element in ElementType.AllElements)
                writer.Write("<th colspan=\"6\">{0}</th>", element.Name);
            writer.WriteLine("<th colspan=\"6\">ВСЕГО</th></tr>");
            writer.Write("<tr>");
            for (int col = 0; col < Cols; col++)
                writer.Write("<th>C</th><th>L</th><th>S</th><th>E</th><th>A</th><th>P</th>");
            writer.WriteLine("</tr>");
            for (int mana = 0; mana < 21; mana++) {
                if (statsMana[mana, 6, cAll] == 0) continue;
                writer.Write("<tr valign=\"top\" align=\"center\"><td rowspan=\"2\">{0}</td>", mana);
                for (int col = 0; col < Cols; col++) {
                    writer.Write("<td colspan=\"4\" bgcolor=\"#F0F0F0\">{0}</td>", ZeroSpace(statsMana[mana,6,col]));
                    writer.Write("<td colspan=\"2\">&nbsp</td>");
                }
                writer.WriteLine("</tr>");
                writer.Write("<tr valign=\"top\">");
                for (int col = 0; col < Cols; col++)
                    for (int t = 0; t < 6; t++)
                        writer.Write("<td>{0}</td>", ZeroSpace(statsMana[mana,t,col]));
                writer.WriteLine("</tr>");
            }
            writer.WriteLine("</table>");

            writer.WriteLine("<br/><br/>");

            writer.WriteLine("<h2>Перечень карт по их завершенности.</h2>");
            writer.WriteLine("<table width=\"100%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">");
            writer.WriteLine("<tr><th>Стихия / завершенность</th><th>Список карт</th></tr>");
            foreach (var element in ElementType.AllElements) {
                writer.WriteLine("<tr><th colspan=\"2\">{0}</th></tr>", element.Name);
                for (int l = 0; l < 5; l++) {
                    writer.Write("<tr valign=\"top\"><td>{0}</td>", RowNames[rLevel+l]);
                    string s = "";
                    for (int t = 0; t < 6; t++) if (!string.IsNullOrEmpty(statsAdd[element.Number, l, t])) {
                        if (!string.IsNullOrEmpty(s)) s += "<br/>";
                        s += "<b>";
                        s += RowNames[rType+t];
                        s += ":</b> ";
                        s += statsAdd[element.Number, l, t];
                    }
                    writer.Write("<td>{0}</td>", string.IsNullOrEmpty(s) ? "&nbsp;" : s);
                    writer.WriteLine("</tr>");
                }
            }
            writer.WriteLine("</table>");

            writer.WriteLine("<h2>Перечень карт по их весам.</h2>");
            writer.WriteLine("<table width=\"100%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">");
            writer.WriteLine("<tr><th>Вес</th><th>Стихия</th><th>Карта</th></tr>");
            foreach (var card in cardsByWeight) {
                writer.WriteLine("<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>", card.Weight, card.Element.Name, string.IsNullOrEmpty(card.CardName) ? card.Id : card.CardName);
            }
            writer.WriteLine("</table>");

            writer.WriteLine("</body>\n</html>");
        }

        private static string ZeroSpace(int i) {
            return i == 0 ? "&nbsp;" : i.ToString();
        }
    }
}
